#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "iot_gpio_ex.h"
#include "iot_adc.h"
#include "iot_pwm.h"

#include "WifiSta.h"
#include "MQTTClient.h"
#include "cJSON.h"
#include "Led.h"
#define SSID "Nice"
#define KEY "12312312"
#define HOST_ADDR "baaeb697c9.st1.iotda-device.cn-north-4.myhuaweicloud.com"
#define SERVICE_ID "Smoke"
#define DEVICE_ID "668f8764a559ef622667d527_Smoke_iot_0_0_2024071107"
#define DEVICE_USER "668f8764a559ef622667d527_Smoke_iot"
#define DEVICE_PWD "2cb8e6cc96ba4f389b27ef3db61febda3aea3332bdb1b4e2c01b770254040636"
#define TOPIC_PUBLISH "$oc/devices/"DEVICE_ID"/sys/properties/report"
#define TPOIC_SUBCRIB "$oc/devices/"DEVICE_USER"/sys/commands/#"
#define TOPIC_RESPONSE "$oc/devices/"DEVICE_USER"/sys/commands/response/"
#define BEEP_Freq 2442
#define beep_GPIO 2
#define adc_GPIO 13

float smoke_adc;
int led_on,hvalue = 80;
char smoke_str[20] = {0};
MQTTClient client;
Network network;
static unsigned char sendBuf[1000];
static unsigned char recvBuf[1000];


void TASK1();
void TASK2();
float GetMq2(void);
void Beep_Init();
void Beep_Set(unsigned short duty);
void Beep_Stop();
void Adc_Init();
void messageHandle(MessageData *data);
void message_Cmdback(char *data);


static void Smoke(void)
{
    printf("ADC Test!\n");
    osThreadAttr_t attr;
    Adc_Init();
    Beep_Init();
    Led_Init();
    attr.name = "AdcGpioTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024 * 5;
    attr.priority = osPriorityNormal;
    osThreadNew(TASK1,NULL,&attr);
    attr.name = "Task2";
    osThreadNew(TASK2,NULL,&attr);
}
void TASK1(void){
    unsigned short value;
    sleep(5);
    while (1) {
        smoke_adc = GetMq2();
        if(smoke_adc > hvalue){
            Beep_Set(20);
            Led_On();
        }else {
            Beep_Stop();
            Led_Off();
        }
        printf("%f",smoke_adc);
        sprintf(smoke_str,"%f",smoke_adc);
        osDelay(100); // 延时1s
    }
}

void TASK2(void){
    WifiConnect(SSID,KEY);   
    NetworkInit(&network);
    Led_Init();
    printf("NetworkInit\n");
begin:    
    NetworkConnect(&network,HOST_ADDR,1883);
    printf("MqttClinetInit\n");
    MQTTClientInit(&client,&network,2000,sendBuf,sizeof(sendBuf),recvBuf,sizeof(recvBuf));
    //配置平台端MQTT连接
    MQTTString clientId = MQTTString_initializer;
    clientId.cstring = DEVICE_ID;
    MQTTString clientUser = MQTTString_initializer;
    clientUser.cstring = DEVICE_USER;
    MQTTString clientPwd = MQTTString_initializer;
    clientPwd.cstring = DEVICE_PWD;
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.clientID = clientId;
    data.username = clientUser;
    data.password = clientPwd;
    data.willFlag = 0;
    data.MQTTVersion = 4;
    data.keepAliveInterval = 60;
    data.cleansession = 1;
    printf("MQTTConect\n");
    int rc = MQTTConnect(&client,&data);
    if(rc != 0){
        printf("MQTTConect %d\n",rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        sleep(2);
        goto begin;
    }
    //配置订阅指令
    printf("MQTTSUBCRIBE\n");
    rc = MQTTSubscribe(&client,TPOIC_SUBCRIB,0,messageHandle);
    if(rc != 0){
        printf("MQTTSubscribe %d\n",rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        sleep(2);
        goto begin;
    }

    while(1){
        MQTTMessage message;
        char payload[100] = {0};
        cJSON *root = cJSON_CreateObject();
        if(root != NULL){
            cJSON *serv_arr = cJSON_AddArrayToObject(root,"services");
            cJSON *arr_item = cJSON_CreateObject();
            cJSON_AddStringToObject(arr_item,"service_id",SERVICE_ID);
            cJSON *pro_obj = cJSON_CreateObject();
            cJSON_AddItemToObject(arr_item,"properties",pro_obj);

            if(led_on == 1) cJSON_AddStringToObject(pro_obj,"Light","ON");
            else if(led_on == 0)  cJSON_AddStringToObject(pro_obj,"Light","OFF");
            cJSON_AddNumberToObject(pro_obj,"Smoke",smoke_adc);

            cJSON_AddItemToArray(serv_arr,arr_item);
            char *play_str = cJSON_PrintUnformatted(root);
            strcpy(payload,play_str);
            cJSON_free(play_str);
            cJSON_Delete(root);
        }
        message.qos = 0;
        message.retained = 0;
        message.payload = payload;
        message.payloadlen = strlen(payload);
        if((rc = MQTTPublish(&client,TOPIC_PUBLISH,&message)) != 0){
            printf("MQTT Publish Failed\n");
            NetworkDisconnect(&network);
            MQTTDisconnect(&client);
            sleep(2);
            goto begin;
        }else {
            printf("mqtt publish success:%s\n",payload);
        }
        MQTTYield(&client,3000);
    }
}
void messageHandle(MessageData *data){
    printf("messeage on topic:%s,data%s\n",data->topicName->lenstring.data,data->message->payload);
    char *request_id_idx = NULL;
    request_id_idx = strstr(data->topicName->lenstring.data,"request_id=");
    char request_id[50] = {0};
    strncpy(request_id,request_id_idx + 11,36);
    printf("requestId = %s\n",request_id);
    cJSON *root = cJSON_ParseWithLength(data->message->payload,data->message->payloadlen);
    if(root != NULL){
        cJSON *cmd_name = cJSON_GetObjectItem(root,"command_name");
        if(cmd_name != NULL){
            char *cmd_name_str = cJSON_GetStringValue(cmd_name);
            printf("command_name :%s\n",cmd_name_str);
            if(strcmp(cmd_name_str,"Control") ==0){
                cJSON *para_obj = cJSON_GetObjectItem(root,"paras");
                cJSON *status_obj = cJSON_GetObjectItem(para_obj,"Light");
                char *light_str = cJSON_GetStringValue(status_obj);
                if(strcmp(light_str,"ON") == 0) {
                    Led_On();
                    led_on = 1;
                }
                else {
                    Led_Off();
                    led_on = 0;
                }
                
                cJSON_free(light_str);
            }
        }
        message_Cmdback(request_id);
        cJSON_Delete(root);
    }
}

//指令返回
void message_Cmdback(char *data){
    char retopic_str[128] = {0};
    sprintf(retopic_str,"%srequest_id=%s",TOPIC_RESPONSE,data);
    printf("retopic = %s\n",retopic_str);
    MQTTMessage message;
    char payload[200] = {0};
    message.qos = 0;
    message.retained = 0;
    sprintf(payload,"{\
    \"result_code\": 0,\
    \"response_name\": \"COMMAND_RESPONSE\",\
    \"paras\": {\
        \"result\": \"success\"\
    }\
    }");
    message.payload = payload;
    message.payloadlen = strlen(payload);
    int rc;
    if((rc = MQTTPublish(&client,retopic_str,&message)) != 0){
        printf("MessageCmdback Publish Failed\n");
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        sleep(2);
    }else {
        printf("MessageCmdback publish success:%s\n",payload);
    }
}

float GetMq2(void){
    unsigned short data;
    IoTAdcRead(6, &data, IOT_ADC_EQU_MODEL_8, IOT_ADC_CUR_BAIS_DEFAULT, 0xFF);
    float smoke = (float)data * 1.8 * 4 / 4096;
    float s;
    s = (5-smoke) / smoke * 0.5;
    smoke = pow(11.5428 * 6.64 / s,0.6549f) * 10;
    return smoke;
}
void Adc_Init(){
    IoTGpioInit(adc_GPIO);
    IoTGpioSetFunc(adc_GPIO,IOT_GPIO_FUNC_GPIO_13_GPIO);
    IoTGpioSetDir(adc_GPIO,IOT_GPIO_DIR_IN);
    IoTGpioSetPull(adc_GPIO,1);
}
void Beep_Init(){
    IoTGpioInit(beep_GPIO);
    IoTGpioSetFunc(beep_GPIO,IOT_GPIO_FUNC_GPIO_2_PWM2_OUT);
    IoTGpioSetDir(beep_GPIO,IOT_GPIO_DIR_OUT);
    IoTPwmInit(2);
}
void Beep_Set(unsigned short duty){
     IoTPwmStart(2, duty, BEEP_Freq);
}
void Beep_Stop(){
    IoTPwmStop(2);
}
APP_FEATURE_INIT(Smoke);